#pragma once
#include <type_traits>

/**
 * @brief 函数模板
 *
 */
namespace cp1
{
    /**
     * @brief 返回最大值  两数相同则返回第一个参数
     */
    template <typename T>
    T max_1(T a, T b)
    {
        auto var = b < a ? a : b;
        std::cout << __func__ << " : " << var << std::endl;
        return var;
    }

    /**
     * @brief 模板重载
     */
    template <typename T>
    T max_1(T a, T b, T c)
    {
        auto var = max_1(max_1(a, b), c);
        std::cout << __func__ << " : " << var << std::endl;
        return var;
    }

    /**
     * @brief 返回类型推导  某些条件下T可能为引用
     */
    template <typename T1, typename T2>
    auto max_2(T1 a, T2 b)
    {
        auto var = b < a ? a : b;
        std::cout << __func__ << " : " << var << std::endl;
        return var;
    }

    /**
     * @brief 声明返回类型并去掉修饰符得到底层类型  确保返回非引用类型
     */
    template <typename T1, typename T2>
    auto max_3(T1 a, T2 b) -> typename std::decay_t<decltype(false ? a : b)>
    {
        auto var = b < a ? a : b;
        std::cout << __func__ << " : " << var << std::endl;
        return var;
    }

    /**
     * @brief 返回公共类型
     */
    template <typename T1, typename T2>
    std::common_type_t<T1, T2> max_4(T1 a, T2 b)
    {
        auto var = b < a ? a : b;
        std::cout << __func__ << " : " << var << std::endl;
        return var;
    }

    /**
     * @brief 默认返回类型
     */
    template <typename T1, typename T2, typename RT = std::common_type_t<T1, T2>>
    RT max_5(T1 a, T2 b)
    {
        auto var = b < a ? a : b;
        std::cout << __func__ << " : " << var << std::endl;
        return var;
    }

};